package pe.edu.unmsm.ocaa.workspace.presentacion.controller.procesos;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.http.HttpServletResponse;

import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.NodeUnselectEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.TreeNode;
import org.primefaces.model.UploadedFile;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import pe.edu.unmsm.ocaa.workspace.negocio.modelo.dto.ArchivoDTO;
import pe.edu.unmsm.ocaa.workspace.negocio.modelo.dto.GrupoDTO;
import pe.edu.unmsm.ocaa.workspace.negocio.modelo.dto.UsuarioDTO;
import pe.edu.unmsm.ocaa.workspace.negocio.modelo.dto.VWUsuarioDTO;
import pe.edu.unmsm.ocaa.workspace.negocio.servicio.ArchivoService;
import pe.edu.unmsm.ocaa.workspace.negocio.servicio.GrupoService;
import pe.edu.unmsm.ocaa.workspace.negocio.servicio.UsuarioService;

@Controller
@Scope("view")
public class ArchivoController {
	/*****************ATRIBUTOS**************/
	private TreeNode rutaRaiz;
	private TreeNode nodoSeleccionado;
	private UploadedFile archivoSubido;
	private ArchivoDTO carpetaEditar;
	private ArchivoDTO archivoSubidoDTO;
	private List<ArchivoDTO> archivosxCarpeta;
	private ArchivoDTO archivoSeleccionado;
	private StreamedContent archivoADescargar;
	private boolean descargaHabilitada;
	private boolean eliminarHabilitado;
	private boolean nuevaCarpHabilitado;
	private boolean subirArchHabilitado;
	private boolean compartirHabilitado;
	private UsuarioDTO usuarioLogueado;
	private GrupoDTO grupoCompartir;
	private List<GrupoDTO> resultGrupoBusq;
	private List<GrupoDTO> listGrupos;
	private GrupoDTO grupoSeleccionado;

	@Resource
	ArchivoService archivoService;
	@Resource
	UsuarioService usuarioService;
	@Resource
	GrupoService grupoService;
	
	/*****************INICIALIZACION**************/
	public ArchivoController() {
		setCarpetaEditar(new ArchivoDTO());
		setArchivoSubidoDTO(new ArchivoDTO());
		setGrupoCompartir(new GrupoDTO());
	}

	private void inicializarBotones() {
		boolean esArchivo=false;
		boolean seleccionado=false;
		if(getArchivoSeleccionado()!=null)
		{
			seleccionado=true;
			if(getArchivoSeleccionado().getTipoArchivo()==2)
				esArchivo=true;
		}
			
		
		switch (getUsuarioLogueado().getPerfilUsuario()) {
		case 1:
			setDescargaHabilitada(esArchivo);
			setSubirArchHabilitado(true);
			setNuevaCarpHabilitado(true);
			setEliminarHabilitado(seleccionado);
			setCompartirHabilitado(seleccionado);
			break;
		case 2:
			setDescargaHabilitada(esArchivo);
			setSubirArchHabilitado(false);
			setNuevaCarpHabilitado(false);
			setEliminarHabilitado(false);
			setCompartirHabilitado(false);
			break;
		case 3:
			setDescargaHabilitada(esArchivo);
			setSubirArchHabilitado(false);
			setNuevaCarpHabilitado(false);
			setEliminarHabilitado(false);
			setCompartirHabilitado(false);
			break;

		default:
			setDescargaHabilitada(false);
			setSubirArchHabilitado(false);
			setNuevaCarpHabilitado(false);
			setEliminarHabilitado(false);
			setCompartirHabilitado(false);
			break;
		}
	}
	
	@PostConstruct
	private void init(){
		setUsuarioLogueado((UsuarioDTO)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("usuarioLogueado"));
		setRutaRaiz(archivoService.cargarCarpetas(getUsuarioLogueado().getIdUsuario()));
		setArchivosxCarpeta(archivoService.cargarArchivosxCarpeta(0, getUsuarioLogueado().getIdUsuario()));
		setCarpetaEditar(new ArchivoDTO());
		setArchivoSubidoDTO(new ArchivoDTO());
		setNodoSeleccionado(null);
		inicializarBotones();
	}
	/*****************NAVEGACION**************/

	public void crearCarpetaEv(ActionEvent ev){
		FacesContext context = FacesContext.getCurrentInstance();
		crearCarpeta();
		setRutaRaiz(archivoService.cargarCarpetas(getUsuarioLogueado().getIdUsuario()));
		setDescargaHabilitada(false);
		context.addMessage(null, new FacesMessage("Exito", "La carpeta se creo correctamente"));
	}

	private void crearCarpeta() {
		if (nodoSeleccionado==null)
			getCarpetaEditar().setIdArchivoPadre(0);	
		else{
			ArchivoDTO nodo=(ArchivoDTO)getNodoSeleccionado().getData();
			getCarpetaEditar().setIdArchivoPadre(nodo.getIdArchivo());
		}
		archivoService.guardarCarpeta(carpetaEditar);
	}
	
	public void cargarArchivosxCarpetaEv(NodeSelectEvent ev){
		cargarArchivosxCarpeta();
	}
	
	public void deseleccionarCarpetas(NodeUnselectEvent ev){
		System.out.println("carpeta deseleccionada");
		setNodoSeleccionado(null);
		inicializarBotones();
	}
	
	public void deseleccionarCarpetasEv(ActionEvent ev){
		System.out.println("carpeta deseleccionada a traves del boton");
		setRutaRaiz(archivoService.cargarCarpetas(getUsuarioLogueado().getIdUsuario()));
		setArchivosxCarpeta(archivoService.cargarArchivosxCarpeta(0, getUsuarioLogueado().getIdUsuario()));
		setNodoSeleccionado(null);
		inicializarBotones();
	}

	private void cargarArchivosxCarpeta() {
		if(getNodoSeleccionado()==null)
			setArchivosxCarpeta(archivoService.cargarArchivosxCarpeta(0, getUsuarioLogueado().getIdUsuario()));
		else
		{
			ArchivoDTO nodo=(ArchivoDTO)getNodoSeleccionado().getData();
			setArchivosxCarpeta(archivoService.cargarArchivosxCarpeta(nodo.getIdArchivo(), getUsuarioLogueado().getIdUsuario()));
		}
		setArchivoSeleccionado(null);
		inicializarBotones();
	}
	
    public void subirArchivo(FileUploadEvent event) throws IOException {
        if(!existeArchivo(event))
        {
        	String nombreArchivoDisco=archivoService.generarSgteNomArchivoDisco(event.getFile().getFileName());
        	guardarArchivoFisico(nombreArchivoDisco, event.getFile().getInputstream());
            guardarArchivoBD(event, nombreArchivoDisco);
            setRutaRaiz(archivoService.cargarCarpetas(getUsuarioLogueado().getIdUsuario()));
            cargarArchivosxCarpeta();
            FacesMessage msg = new FacesMessage("Exito", event.getFile().getFileName() + " esta Subido.");        
            FacesContext.getCurrentInstance().addMessage(null, msg);	
        }
        else
        {
        	FacesMessage msg = new FacesMessage("Aviso","El " + event.getFile().getFileName() + " ya existe.");        
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
		inicializarBotones();
    }

	private boolean existeArchivo(FileUploadEvent event) {
		Integer idPadre;
		if(getNodoSeleccionado()==null)
			idPadre=0;
		else
		{
			ArchivoDTO nodo=(ArchivoDTO)getNodoSeleccionado().getData();
			idPadre=nodo.getIdArchivo();
		}
		return archivoService.existeArchivoenCarpeta(event.getFile().getFileName(), idPadre);
	}

	private void guardarArchivoBD(FileUploadEvent event, String nombreArchivoDisco) {
		getArchivoSubidoDTO().setNombreArchivoDisco(nombreArchivoDisco);
		getArchivoSubidoDTO().setNombreArchivoVirtual(event.getFile().getFileName());
        if(getNodoSeleccionado()==null)
        	getArchivoSubidoDTO().setIdArchivoPadre(0);
        else
        {
        	ArchivoDTO nodo=(ArchivoDTO)getNodoSeleccionado().getData();
        	getArchivoSubidoDTO().setIdArchivoPadre(nodo.getIdArchivo());
        }
        archivoService.guardarArchivo(getArchivoSubidoDTO());
	}  	
    
    
	public void guardarArchivoFisico(String fileName, InputStream in) {
		try {
			String destination = "C:\\ocaa\\";
			// write the inputStream to a FileOutputStream
			OutputStream out = new FileOutputStream(new File(destination
					+ fileName));

			int read = 0;
			byte[] bytes = new byte[1024];

			while ((read = in.read(bytes)) != -1) {
				out.write(bytes, 0, read);
			}

			in.close();
			out.flush();
			out.close();
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
	}
	public void cargarPermisosxCarpeta(ActionEvent ev){
		if(getArchivoSeleccionado()!=null)
			setListGrupos(grupoService.listarGruposxArchivo(getArchivoSeleccionado().getIdArchivo()));
		else
			setListGrupos(new ArrayList<GrupoDTO>());
	}
    
    public List<String> complete(String query) {  
    	setResultGrupoBusq(grupoService.listarGruposxLikeNom(query));
    	List<String> results = new ArrayList<String>();
    	for (GrupoDTO grupoDTO : getResultGrupoBusq()) {
			results.add(grupoDTO.getNomGrupo());
		}
        return results;  
    }  
    
    public void handleSelect(SelectEvent event) {  
    	String nick=event.getObject().toString();
    	for (GrupoDTO grupoDTO : getResultGrupoBusq()) {
			if (grupoDTO.getNomGrupo().equals(nick))
				setGrupoCompartir(grupoDTO);
		} 
    	System.out.println("grupo seleccionado "+getGrupoCompartir().getIdGrupo()+getGrupoCompartir().getNomGrupo());
    }  
    
    public void guardarPermiso(ActionEvent ev){
    	archivoService.guardarPermisoxCarpeta(getGrupoCompartir(), getArchivoSeleccionado());
    	setGrupoCompartir(new GrupoDTO());
    	cargarPermisosxCarpeta(ev);
    }
    
    public void descargarArchivoEv(ActionEvent ev) {
        try {     
            descargarArchivo();
            cargarArchivosxCarpeta();				
        } catch (IOException ex) {
            System.out.println("Error : " + ex);
        }
    }

	private void descargarArchivo() throws FileNotFoundException, IOException {
		File file = new File("C:\\ocaa\\" + getArchivoSeleccionado().getNombreArchivoDisco());
		InputStream fis = new FileInputStream(file);
		byte[] buf = new byte[(int)file.length()];
		int offset = 0;
		int numRead = 0;
		while ((offset < buf.length) && ((numRead = fis.read(buf, offset, buf.length - offset)) >= 0))
		{
		    offset += numRead;
		}
		fis.close();
		HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
		response.setContentType("application/octet-stream");
		response.setHeader("Content-Disposition", "attachment;filename=" + getArchivoSeleccionado().getNombreArchivoVirtual() + "");
		response.getOutputStream().write(buf);
		response.getOutputStream().flush();
		response.getOutputStream().close();
		FacesContext.getCurrentInstance().responseComplete();
	}
	
	public void actualizarBotones(SelectEvent ev)
	{
		inicializarBotones();
	}
	
	public void eliminarArchivo(ActionEvent ev){
		String msje="";
		if (!getArchivoSeleccionado().getIdArchivo().equals(86)) {
			archivoService.eliminarArchivo(getArchivoSeleccionado().getIdArchivo());
	        setRutaRaiz(archivoService.cargarCarpetas(getUsuarioLogueado().getIdUsuario()));
	        cargarArchivosxCarpeta();	
	        msje="El archivo/carpeta se elimino correctamente.";
		}
		else{
			msje="No se puede eliminar, es un archivo de sistema";
		}
		
		FacesMessage msg = new FacesMessage("Exito", msje);        
        FacesContext.getCurrentInstance().addMessage(null, msg);
	}
	
    public void eliminarGrupoSeleccionado(){
    	List<GrupoDTO> listg=getListGrupos();
    	archivoService.eliminarGrupoxArchivo(getGrupoSeleccionado().getIdGrupo(),getArchivoSeleccionado());
    	for (int i=0; i< listg.size();i++) {
    		GrupoDTO grupoDTO=listg.get(i);
			if(grupoDTO.getIdGrupo().equals(getGrupoSeleccionado().getIdGrupo()))
				listg.remove(i);
		}
    }
    
    public void limpiarCarpeta(ActionEvent ev){
    	setCarpetaEditar(new ArchivoDTO());
    }

	/*****************GETTERS AND SETTERS**************/
	
	public TreeNode getRutaRaiz() {
		return rutaRaiz;
	}

	public void setRutaRaiz(TreeNode rutaRaiz) {
		this.rutaRaiz = rutaRaiz;
	}

	public TreeNode getNodoSeleccionado() {
		return nodoSeleccionado;
	}

	public void setNodoSeleccionado(TreeNode nodoSeleccionado) {
		this.nodoSeleccionado = nodoSeleccionado;
	}

	public UploadedFile getArchivoSubido() {
		return archivoSubido;
	}

	public void setArchivoSubido(UploadedFile archivoSubido) {
		this.archivoSubido = archivoSubido;
	}

	public ArchivoDTO getCarpetaEditar() {
		return carpetaEditar;
	}

	public void setCarpetaEditar(ArchivoDTO carpetaEditar) {
		this.carpetaEditar = carpetaEditar;
	}

	public List<ArchivoDTO> getArchivosxCarpeta() {
		return archivosxCarpeta;
	}

	public void setArchivosxCarpeta(List<ArchivoDTO> archivosxCarpeta) {
		this.archivosxCarpeta = archivosxCarpeta;
	}

	public ArchivoDTO getArchivoSubidoDTO() {
		return archivoSubidoDTO;
	}

	public void setArchivoSubidoDTO(ArchivoDTO archivoSubidoDTO) {
		this.archivoSubidoDTO = archivoSubidoDTO;
	}

	public ArchivoDTO getArchivoSeleccionado() {
		return archivoSeleccionado;
	}

	public void setArchivoSeleccionado(ArchivoDTO archivoSeleccionado) {
		this.archivoSeleccionado = archivoSeleccionado;
	}

	public StreamedContent getArchivoADescargar() {
		return archivoADescargar;
	}

	public void setArchivoADescargar(StreamedContent archivoADescargar) {
		this.archivoADescargar = archivoADescargar;
	}

	public boolean isDescargaHabilitada() {
		return descargaHabilitada;
	}

	public void setDescargaHabilitada(boolean descargaHabilitada) {
		this.descargaHabilitada = descargaHabilitada;
	}

	public boolean isEliminarHabilitado() {
		return eliminarHabilitado;
	}

	public void setEliminarHabilitado(boolean eliminarHabilitado) {
		this.eliminarHabilitado = eliminarHabilitado;
	}

	public UsuarioDTO getUsuarioLogueado() {
		return usuarioLogueado;
	}

	public void setUsuarioLogueado(UsuarioDTO usuarioLogueado) {
		this.usuarioLogueado = usuarioLogueado;
	}
	public boolean isNuevaCarpHabilitado() {
		return nuevaCarpHabilitado;
	}

	public void setNuevaCarpHabilitado(boolean nuevaCarpHabilitado) {
		this.nuevaCarpHabilitado = nuevaCarpHabilitado;
	}

	public boolean isSubirArchHabilitado() {
		return subirArchHabilitado;
	}

	public void setSubirArchHabilitado(boolean subirArchHabilitado) {
		this.subirArchHabilitado = subirArchHabilitado;
	}

	public boolean isCompartirHabilitado() {
		return compartirHabilitado;
	}

	public void setCompartirHabilitado(boolean compartirHabilitado) {
		this.compartirHabilitado = compartirHabilitado;
	}

	public GrupoDTO getGrupoCompartir() {
		return grupoCompartir;
	}

	public void setGrupoCompartir(GrupoDTO grupoCompartir) {
		this.grupoCompartir = grupoCompartir;
	}

	public List<GrupoDTO> getResultGrupoBusq() {
		return resultGrupoBusq;
	}

	public void setResultGrupoBusq(List<GrupoDTO> resultGrupoBusq) {
		this.resultGrupoBusq = resultGrupoBusq;
	}

	public List<GrupoDTO> getListGrupos() {
		return listGrupos;
	}

	public void setListGrupos(List<GrupoDTO> listGrupos) {
		this.listGrupos = listGrupos;
	}

	public GrupoDTO getGrupoSeleccionado() {
		return grupoSeleccionado;
	}

	public void setGrupoSeleccionado(GrupoDTO grupoSeleccionado) {
		this.grupoSeleccionado = grupoSeleccionado;
	}
}
